<?php 
class decoder{

	private $fillLevel = 10;
	private $maxSplitLevel = 3;
	private $minLetterWidth = 15;
	private $removeLevel = 1;
    private $YNoise = 2;
	private $img = null;
	private $w = null;
	private $h = null;
	private $testSmooth = null;
	private $test = array(array(0,0,0),array(0,0,0),array(0,0,0));
	
	private function imagecoloratRGB($image,$x,$y){
		$rgb = imagecolorat($image, $x, $y);
		$res = imagecolorsforindex($image, $rgb);
		return $res;
	}
	
	public function load($file){
		$this->img = imagecreatefromgif($file);
		$size = getimagesize($file);
		$this->w = $size[0]; 
		$this->h = $size[1];
	}

	public function show(){
		header('Content-Type: image/gif');
		imagegif($this->img);
	}
	
	public function imagesetpixel($image, $x, $y, $color){
		return imagesetpixel($image, $x, $y, $color);
	}
	
	public function removeNoise(){
		$tmp = imagecreatetruecolor($this->w, $this->h);
		$white = imagecolorallocate($tmp, 255, 255, 255);
		$black = imagecolorallocate($tmp, 0, 0, 0);
		imagefill($tmp, 0, 0, $white);
		$stat = array();
		for($x=0;$x<$this->w;$x++){
			for($y=0;$y<$this->h;$y++){
				$colors = $this->imagecoloratRGB($this->img, $x, $y);
				$color = (string)imagecolorat($this->img,$x,$y);
				if (!isset($stat[$color])) $stat[$color] = 1; 
				else $stat[$color]++;
			}
		}
		array_filter($stat);arsort($stat);
		//var_dump($stat);die();
		for($x=0;$x<$this->w;$x++){
			for($y=0;$y<$this->h;$y++){
				$colors = $this->imagecoloratRGB($this->img, $x, $y);
				$color = (string)imagecolorat($this->img,$x,$y);
				if(isset($stat[$color]) && $stat[$color]>30 && $stat[$color]<300 && $color!=0 && $color!=167){ 
				//if($color!=164 && $color!=0 && $color!=13 && $color!=$_GET['c']){
					imagesetpixel($tmp, $x, $y, $black);
					if (!isset($stat[$color])) $stat[$color] = 0; 
					else $stat[$color]++;
				}
			}
		}
		imagedestroy($this->img);
		$this->img = $tmp;
	}

	public function smooth(){
		$tmp = imagecreatetruecolor($this->w, $this->h);
		$white = imagecolorallocate($tmp, 255, 255, 255);
		$black = imagecolorallocate($tmp, 0, 0, 0);
		for($x=0;$x<$this->w;$x++){
			for($y=0;$y<$this->h;$y++){
				$dot = $this->dotSmooth($x, $y);
				if ($dot>=$this->fillLevel) $this->imagesetpixel($tmp, $x, $y, $black);				
				if ($dot<=$this->removeLevel) $this->imagesetpixel($tmp, $x, $y, $white);
				else $this->imagesetpixel($tmp, $x, $y, imagecolorat($this->img, $x, $y)); 				
			}
		}
		imagedestroy($this->img);
		$this->img = $tmp;
	}
	
	public function dotSmooth($x,$y){
		$dotMarks = 0;
		$totalMarks = 0;
		$colors = $this->imagecoloratRGB($this->img, $x, $y);
		if (array_sum($colors)==0) //black color
			$dotMarks++;
		for($level=1;$level<=2;$level++){
			$ly1 = $y+$level;
			$ly2 = $y-$level;
			for($lx=$x-$level;$lx<=$x+$level;$lx++){
				if ($lx<0 or  $lx>=$this->w) continue;
				if ($ly1>=0 and $ly1<$this->h){
					$colors = $this->imagecoloratRGB($this->img, $lx, $ly1);
					if (array_sum($colors)==0) //black color
						$dotMarks++;
				}
				if ($ly2>=0 and $ly2<$this->h){
					$colors = $this->imagecoloratRGB($this->img, $lx, $ly2);
					if (array_sum($colors)==0) //black color
						$dotMarks++;
				}
				$totalMarks++;
			}
			$lx1 = $x+$level;
			$lx2 = $x-$level;
			for($ly=$x-$level+1;$ly<=$x+$level-1;$ly++){
				if ($ly<0 or  $ly>=$this->h) continue;
				if ($lx1>=0 and $lx1<$this->w){
					$colors = $this->imagecoloratRGB($this->img, $lx1, $ly);
					if (array_sum($colors)==0) //black color
						$dotMarks++;
				}
				if ($lx2>=0 and $lx2<$this->w){
					$colors = $this->imagecoloratRGB($this->img, $lx2, $ly);
					if (array_sum($colors)==0) //black color
						$dotMarks++;
				}
				$totalMarks++;
			}
		}
		return $dotMarks;
	}

	public function splitLetters(){
		$tmp = imagecreatetruecolor($this->w, $this->h);
		$white = imagecolorallocate($tmp, 255, 255, 255);
		$black = imagecolorallocate($tmp, 0, 0, 0);
		$prevDividerX = 0;
		$emptySequence = 0;
		for($x=0;$x<$this->w;$x++){
			$empty = true;
			$noiseLevel = 0;
			for($y=0;$y<$this->h;$y++){
				$colors = $this->imagecoloratRGB($this->img, $x, $y);
				if (array_sum($colors)==0){
					if ($noiseLevel<$this->maxSplitLevel) $noiseLevel++;
					else {$empty=false;break;}
				}
			}
			if ($empty){
				$emptySequence++;
				if (($x-$prevDividerX)>=$this->minLetterWidth){
					$this->drawDivider($x);
					if (($x-$prevDividerX)>=($this->minLetterWidth*2)){
						$this->drawDivider($prevDividerX+round(($x-$prevDividerX)/2));
						$this->drawDividerY($prevDividerX,$prevDividerX+round(($x-$prevDividerX)/2));
						$this->drawDividerY($prevDividerX+round(($x-$prevDividerX)/2),$x);
					}
					else{
						$this->drawDividerY($prevDividerX,$x);
					}
					$prevDividerX = $x;
				}
			}
			else{
				if ($emptySequence>2){
					$this->drawDivider($prevDividerX,$prevDividerX+$emptySequence);
					$prevDividerX+=$emptySequence;
				}
				$emptySequence = 0;
			}
		}
		//imagedestroy($this->img);
		//$this->img = $tmp;
	}
	
	function drawDivider($x1,$x2=null){
		if (!$x2) $x2=$x1;
		$red = imagecolorallocate($this->img, 100, 0, 0);
		for($i=$x1;$i<=$x2;$i++){
			if ($i>=0 && $i<$this->w)
				for($y=0;$y<$this->h;$y++)
					imagesetpixel($this->img, $i, $y, $red);
		}
	}
	

    function drawDividerY($x1,$x2=null){
        //echo "<br/><br/><br/>x1: $x1, x2: $x2<br/>";
		$red = imagecolorallocate($this->img, 100, 0, 0);
		$topDivider = -1;
		for($y=0;($y<$this->h && $topDivider==-1);$y++){
			$lineNoise = 0;
			for($i=$x1;$i<=$x2;$i++){
				if ($i>=0 && $i<$this->w){
                    $colors = $this->imagecoloratRGB($this->img, $i, $y);
                    if (array_sum($colors)==0){
                        $lineNoise++;
                        //echo "$y:  ".$colors['red']." ".$colors['green']." ".$colors['blue']." (".array_sum($colors).", $lineNoise)<br/>";
                        if ($lineNoise>$this->YNoise){
                            //echo "topDivider:".
                            $topDivider = ($y>0)?$y-1:$y;
                            break;
                        }
                    }
                }
			}
		}
		for($y=0;$y<$topDivider;$y++){
			for($i=$x1;$i<=$x2;$i++){
				if ($i>=0 && $i<$this->w)
				imagesetpixel($this->img, $i, $y, $red);
			}
		}
        $topDivider = -1;
        for($y=$this->h-1;($y>=0 && $topDivider==-1);$y--){
            $lineNoise = 0;
            for($i=$x1;$i<=$x2;$i++){
                if ($i>=0 && $i<$this->w){
                    $colors = $this->imagecoloratRGB($this->img, $i, $y);
                    if (array_sum($colors)==0){
                        $lineNoise++;
                        //echo "$y:  ".$colors['red']." ".$colors['green']." ".$colors['blue']." (".array_sum($colors).", $lineNoise)<br/>";
                        if ($lineNoise>$this->YNoise){
                            //echo "topDivider:".
                            $topDivider = ($y<$this->h)?$y+1:$y;
                            break;
                        }
                    }
                }
            }
        }
        for($y=$this->h-1;$y>$topDivider;$y--){
            for($i=$x1;$i<=$x2;$i++){
                if ($i>=0 && $i<$this->w){
                    imagesetpixel($this->img, $i, $y, $red);
                }
            }
        }
	}
}
?>